#include "StdThreadPool.h"
#include "DoubleLinkList.h"
#include "LinkQueue.h"
#include "StdThread.h"

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <unistd.h>
typedef struct
{
    void* (*func)(void*);
    void *arg;
}Task;

Task* CreateTask(void* (*func)(void*),void *arg)
{
    Task *t = (Task *)malloc(sizeof(Task));
    if(t == NULL)
    {
        printf("CreateTask malloc error!\n");
        return NULL;
    }
    t->func = func;
    t->arg = arg;
    return t;
}

struct StdThreadPool
{
    DLlist threads; //线程链表
    LQueue* taskQueue; //任务队列
    int MaxThrdNum; //最大线程数
    int MinThrdNum; //最小线程数
    int MaxQueueSize; //最大任务数量

    int BusyThrdNum; //忙碌线程数量
    int MinusNum; //需要减少的线程
    Mutex* BusyThrdMutex; //忙线程锁

    Mutex* PoolMutex; //线程池锁
    Cond* QueueNotFull; //队列不满的条件变量
    Cond* QueueNotEmpty; //队列不为空的条件变量

    Thread *manager; //管理者线程
    int SleepTime; //管理者线程的管理间隔
    bool IsClose; //是否关闭线程池
};


bool IsThreadEqual(void *thread1,void *thread2)
{
    Thread *t = (Thread*)thread1;
    return IsCurrentThread(t);
}

void* ThreadWork(void* arg)
{
    ThreadP *p = (ThreadP*)arg;
    while(p->IsClose == false)
    {
        //取任务
        MutexLock(p->PoolMutex);
        //任务队列为空
        while(IsQueueEmpty(p->taskQueue) == true)
        {
            CondWait(p->QueueNotEmpty,p->PoolMutex);

            if(p->IsClose == true)
            {
                MutexUnlock(p->PoolMutex);
                ThreadExit();
            }

            //如果需要削减线程
            if(p->MinusNum > 0)
            {
                //线程退出
                RemoveByElement(&p->threads,NULL,IsThreadEqual,free);
                p->MinusNum--;
                MutexUnlock(p->PoolMutex);
                ThreadExit();
            }
        }
        Task * t = (Task*)*GetQFront(p->taskQueue);
        QPop(p->taskQueue);
        CondSignal(p->QueueNotFull);
        MutexUnlock(p->PoolMutex);


        MutexLock(p->BusyThrdMutex);
        p->BusyThrdNum++;
        MutexUnlock(p->BusyThrdMutex);

        //做任务
        t->func(t->arg);

        MutexLock(p->BusyThrdMutex);
        p->BusyThrdNum--;
        MutexUnlock(p->BusyThrdMutex);

        //销毁任务
        free(t);
    }
    return NULL;
}

//管理者线程
void* ThreadManager(void *arg)
{
    ThreadP *p = (ThreadP*)arg;
    while(p->IsClose == false)
    {
        sleep(p->SleepTime);
        MutexLock(p->PoolMutex);

        //线程多了
        if(p->BusyThrdNum *2 <=p->threads.len)
        {
            p->MinusNum = (p->threads.len - p->BusyThrdNum)/2;
            if(p->threads.len - p->MinThrdNum < p->MinusNum)
                p->MinusNum = p->threads.len - p->MinThrdNum;
            CondBroadcast(p->QueueNotEmpty);
        }
        //线程少了
        else if(GetQueueLen(p->taskQueue) >= p->BusyThrdNum)
        {
            int addNum = GetQueueLen(p->taskQueue) / 2;
            if(addNum + p->threads.len >= p->MaxThrdNum)
                addNum = p->MaxThrdNum - p->threads.len;
            for(int i = 0; i < addNum; i++)
            {
                Thread *t = ThreadInit(ThreadWork,p);
                InsertDLlistTial(&p->threads,t); //插入新的线程
            }
        }
        MutexUnlock(p->PoolMutex);
    }
    return NULL;
}

ThreadP * ThreadPoolInit(int MaxThrdNum,int MinThrdNum,int MaxQueueSize,int SleepTime)
{
    ThreadP *pool = (ThreadP*)malloc(sizeof(ThreadP));
    if(pool == NULL)
    {
        printf("ThreadPoolInit malloc error!\n");
        return NULL;
    }

    InitDLlist(&pool->threads); //线程列表初始化
    pool->taskQueue = InitLQueue(); //任务队列初始化

    pool->PoolMutex = MutexInit(); //初始化线程池锁
    pool->BusyThrdMutex = MutexInit();//忙线程锁

    pool->QueueNotFull = CondInit(); //初始化队列不满的条件变量
    pool->QueueNotEmpty = CondInit(); //初始化队列不空的条件变量
    

    pool->MaxQueueSize = MaxQueueSize;
    pool->MaxThrdNum = MaxThrdNum;
    pool->MinThrdNum = MinThrdNum;
    pool->BusyThrdNum = 0;
    pool->MinusNum = 0;
    
    pool->IsClose = false;

    for(int i = 0; i < pool->MaxThrdNum; i++)
    {
        Thread *t = ThreadInit(ThreadWork,pool);
        InsertDLlistTial(&pool->threads,t); //插入新的线程
    }

    pool->manager = ThreadInit(ThreadManager,pool);
    pool->SleepTime = SleepTime;

    return pool;
}

void ThreadPoolAddTask(ThreadP * p, void *(* func)(void *), void * arg)
{
    MutexLock(p->PoolMutex);
    //任务已经达到上限
    while(GetQueueLen(p->taskQueue) == p->MaxQueueSize)
    {
        //等待队列不满的条件
        CondWait(p->QueueNotFull,p->PoolMutex);
        if(p->IsClose == true)
        {
            MutexUnlock(p->PoolMutex);
            return;
        }
    }

    QPush(p->taskQueue,CreateTask(func,arg));
    CondSignal(p->QueueNotEmpty);
    MutexUnlock(p->PoolMutex);
}

void ClearThreadPool(ThreadP * p)
{
    p->IsClose = true;

    //管理线程回收
    ThreadJoin(p->manager);
    ClearThread(p->manager);

    //任务队列回收
    CondBroadcast(p->QueueNotFull);
    ClearLQueue(p->taskQueue,free);

    //线程列表回收
    CondBroadcast(p->QueueNotEmpty);
    for(int i = 0; i < p->threads.len; i++)
    {
        ThreadJoin(*FindByIndex(&p->threads,i));
    }
    ClearDLlist(&p->threads,free);

    //锁和条件变量
    ClearMutex(p->BusyThrdMutex);
    ClearMutex(p->PoolMutex);

    ClearCond(p->QueueNotEmpty);
    ClearCond(p->QueueNotFull);

    free(p);
}
